#include "./readbitmap.h"
#include "math.h"
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include "defs.h"

int matYCmp(int **yuvYData1,int **yuvYdata2,int N,int M,int tolerate){
    int i=0;
    int j=0;
    int missCnt=0;
    for(i=0;i<N;i++){
        for(j=0;j<M;j++){
            if(yuvYData1[i][j]!=yuvYdata2[i][j]){
                missCnt++;
                if(missCnt>=tolerate){
                    // printf("misscoutn %d\n",missCnt);
                    return -1;
                }
            }
        }
    }   
    return 0;
}

int matCmp(int ***yuvData1,int ***yuvData2,int N,int M,int tolerate){
    int i=0;
    int j=0;
    int **yuv_yData1 = (int **)calloc_mat_int(DY,DX);
    int **yuv_yData2 = (int **)calloc_mat_int(DY,DX);
    putYinBlock(yuv_yData1,yuvData1,block32,block32);
    putYinBlock(yuv_yData2,yuvData2,block32,block32);
    int missCnt=0;
    for(i=0;i<N;i++){
        for(j=0;j<M;j++){
            if(yuv_yData1[i][j]!=yuv_yData2[i][j]){
                missCnt++;
                if(missCnt>=tolerate){
                    // printf("misscoutn %d\n",missCnt);
                    return -1;
                }
            }
        }
    }   
    return 0;
}


int **getYuvYMat(char *path){
     BmpInfo *bmp = readBmp(path);

    int **BlockPosition = (int **)calloc_mat_int(DY, 2);
    int ***rgbData = (int ***)calloc_mat_int3(DY,DX,4);
    int ***yuvData = (int ***)calloc_mat_int3(DY,DX,3);
    int **yuv_yData = (int **)calloc_mat_int(DY,DX);
    getBlockPosition(BlockPosition,X1,Y1,X2,Y2);
    getBlockRgbaData(bmp->rgbData, BlockPosition, rgbData, DY);
    getBlockRgbaData(bmp->rgbData, BlockPosition, rgbData, DY);
    getYuvfromRgb(rgbData, yuvData,block32,block32);
    putYinBlock(yuv_yData,yuvData,block32,block32);

    return yuv_yData;
}
int comp(const void*a,const void*b)//用来做比较的函数。
{
    return *(int*)a-*(int*)b;
}

#define MAX_PATH_LEN (256)
#define PIC_INDEX_LEN (5)
int caculateLoop(char *path){
    int * indexArr=(int *)calloc(100,sizeof(int));
    int index=0;
    printf("caculateLoop\n");
    DIR *d=NULL;
    struct  dirent *dp = NULL;
    struct stat st;
    char*  tmppath =(int *) calloc(100,sizeof(char));
    char* temindex=(int *)calloc(PIC_INDEX_LEN,sizeof(int));
    char*  abspath =(int *) calloc(MAX_PATH_LEN,sizeof(char));
    int **yuvYData1=(int **)calloc_mat_int(DY,DX);
    int **yuvYData2=(int **)calloc_mat_int(DY,DX);
    int init=0;

    if(stat(path,&st)<0||!S_ISDIR(st.st_mode))
    {
        printf("invalid path:%s \n",path);
        return -1;
    }
    if(!(d=opendir(path))){
        printf("opendir error : %s \n",path);
    }
    while ((dp=readdir(d))!=NULL){
        if(!strncmp(dp->d_name,".",1)||!strncmp(dp->d_name,"..",2))
            continue;
        if(!S_ISDIR(st.st_mode))
            continue;
        if(strstr(dp->d_name,".bmp")==NULL){
            continue;
        }
        if(!init){
            strcat(abspath,path);
            strcat(abspath,"/");
            strcpy(tmppath,abspath);
            strcat(tmppath,dp->d_name);
            printf("init data1 using %s\n",tmppath);
            yuvYData1=getYuvYMat(tmppath);
            init=1;
        }
        strcpy(tmppath,abspath);
        strcat(tmppath,dp->d_name);
        yuvYData2=getYuvYMat(tmppath);
        // printf("init data1 using %s\n",tmppath);
        if(!matYCmp(yuvYData1,yuvYData2,block32,block32,0)){
            printf("find same mat in pic %s %s\n",path,dp->d_name);
            memset(temindex,'\0',PIC_INDEX_LEN);
            strncpy(temindex,dp->d_name,4);
            indexArr[index++]=atoi(temindex);
            //  printf("%d %d \n",atoi(temindex),indexArr[index-1]);
        }
    }
    qsort(indexArr,index,sizeof(indexArr[0]),comp);
    int i=0;
    for(i=0;i<index;i++){
        printf(" %d ",indexArr[i]);
    }
    printf("\n");
    for(i=1;i<index;i++){
        printf(" %d ",indexArr[i]-indexArr[i-1]);
    }
    closedir(d);
    return 0;
}

int caculateMBResidual(int ***yuvData1,int ***yuvData2,int ***residualData,int N,int M){
    int i=0;
    int j=0;
    for(i=0;i<N;i++)
        for(j=0;j<M;j++){
            residualData[i][j][0] = yuvData1[i][j][0]-yuvData2[i][j][0];
            residualData[i][j][1]=yuvData1[i][j][1]-yuvData2[i][j][1];
            residualData[i][j][2]=yuvData1[i][j][2]-yuvData2[i][j][2];
        }
    return 0;
}
int*** getYUVMBFromBmp( BmpInfo *bmp,int MB_X,int MB_Y){


    int **BlockPosition = (int **)calloc_mat_int(DY, 2);
    int ***rgbData = (int ***)calloc_mat_int3(DY,DX,4);
    int ***yuvData = (int ***)calloc_mat_int3(DY,DX,3);
    getBlockPosition(BlockPosition,MB_X*32,MB_Y*32,(MB_X*32+DX-1),(MB_Y*32+DY-1));
    getBlockRgbaData(bmp->rgbData, BlockPosition, rgbData, DY);
    getBlockRgbaData(bmp->rgbData, BlockPosition, rgbData, DY);
    getYuvfromRgb(rgbData, yuvData, block32, block32);
    return yuvData;
}


ResidualMB *  caculatePicResidual(char * curPic,char *refPic,int MB_W,int MB_H ){
    printf("cacualte pic residual \n");
    BmpInfo *bmpCur = readBmp(curPic);
    BmpInfo *bmpRef = readBmp(refPic);
    int ***yuvDataCur=NULL;
    int ***yuvDataRef=NULL;

    ResidualMB* R_array=(int *)calloc(Residual_MB_NUM,sizeof(ResidualMB));
    memset(R_array,0,Residual_MB_NUM*sizeof(ResidualMB));
    int index=0;
    int i=0,j=0;
    for(i=0;i<MB_W;i++)
        for(j=0;j<MB_H;j++){

          int ***yuvDataResidual = (int ***)calloc_mat_int3(DY,DX,3);

            yuvDataCur=getYUVMBFromBmp(bmpCur,i,j);
            yuvDataRef=getYUVMBFromBmp(bmpRef,i,j);
            if(!matCmp(yuvDataCur,yuvDataRef,block32,block32,0))
                continue;
            caculateMBResidual(yuvDataCur,yuvDataRef,yuvDataResidual,block32,block32);
            R_array[index].MBIdx=i+j*MB_W;
            R_array[index++].yuvDataResidual=yuvDataResidual;
            // printf("i %d j %d\n",i,j);
        }
    printf("int total %d MBS ,%d MB has residual\n",MB_W*MB_H,index);
    return R_array;
}

int *** readBlock(char *path){
      int count = 0;
    FILE* fp;
    char str[100];
    unsigned  int size=block32*block32*3;
    // uint8_t *** data=calloc(size,sizeof(uint8_t));
    int ***data=(int ***)calloc_mat_int3(DY,DX,3);
    fp = fopen(path, "r");
    int i=0,j=0,k=0;
    if(fp==NULL) printf("bad file path  \n");
    while (fscanf(fp, "%s", str) != EOF)
    {
        // printf("%s\n", str);
        data[j][i][k]=atoi(str);
        // printf("%d\n", data[count]);
        i++;
        if(i==block32){
            i=0;
            j++;
        }
        if(j==block32){
            j=0;
            k++;
        }
        
        count++;
    }
    fclose(fp);
    // print3Arr(data);
    return data;
}


// static void saveBmpFile_copy(unsigned char* pImgData, int width, int height, int imgLength, int i, int j)
// {
//     char fileName[400] = { 0 };
//     sprintf(fileName, "c:\\Source_code\\Client_code_Win\\tmp_dump\\%d.%d.bmp", i, j);

//     BITMAPFILEHEADER bmheader;
//     memset(&bmheader, 0, sizeof(bmheader));
//     bmheader.bfType = 0x4d42;     //image tyoe must be 'BM'
//     bmheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); //head info size
//     bmheader.bfSize = imgLength + bmheader.bfOffBits; //file size

//     BITMAPINFOHEADER bmInfo;
//     memset(&bmInfo, 0, sizeof(bmInfo));
//     bmInfo.biSize = sizeof(bmInfo);
//     bmInfo.biWidth = width;
//     bmInfo.biHeight = -height;
//     bmInfo.biPlanes = 1;
//     bmInfo.biBitCount = 32;
//     bmInfo.biCompression = BI_RGB;

//     HANDLE hFile = CreateFileA(fileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
//     if (hFile != INVALID_HANDLE_VALUE) {
//         DWORD dwWritten;
//         BOOL bRet = WriteFile(hFile, &bmheader, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
//         bRet = WriteFile(hFile, &bmInfo, sizeof(BITMAPINFOHEADER), &dwWritten, NULL);
//         bRet = WriteFile(hFile, pImgData, imgLength, &dwWritten, NULL);
//         CloseHandle(hFile);
//     }
// }
